home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / lib / c / net / gethostnamadr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-03-30  |  7.9 KB  |  399 lines

  1. /*
  2.  * Copyright (c) 1985, 1988 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that this notice is preserved and that due credit is given
  7.  * to the University of California at Berkeley. The name of the University
  8.  * may not be used to endorse or promote products derived from this
  9.  * software without specific prior written permission. This software
  10.  * is provided ``as is'' without express or implied warranty.
  11.  */
  12.  
  13. #if defined(LIBC_SCCS) && !defined(lint)
  14. static char sccsid[] = "@(#)gethostnamadr.c    6.33 (Berkeley) 4/13/88";
  15. #endif /* LIBC_SCCS and not lint */
  16.  
  17. #include <sys/param.h>
  18. #include <sys/socket.h>
  19. #include <netinet/in.h>
  20. #include <ctype.h>
  21. #include <netdb.h>
  22. #include <stdio.h>
  23. #include <errno.h>
  24. #include <arpa/inet.h>
  25. #include <arpa/nameser.h>
  26. #include <resolv.h>
  27.  
  28. #define    MAXALIASES    35
  29. #define    MAXADDRS    35
  30.  
  31. static char *h_addr_ptrs[MAXADDRS + 1];
  32.  
  33. static struct hostent host;
  34. static char *host_aliases[MAXALIASES];
  35. static char hostbuf[BUFSIZ+1];
  36. static struct in_addr host_addr;
  37. static char HOSTDB[] = "/etc/hosts";
  38. static FILE *hostf = NULL;
  39. static char hostaddr[MAXADDRS];
  40. static char *host_addrs[2];
  41. static int stayopen = 0;
  42. static char *any();
  43.  
  44. #if PACKETSZ > 1024
  45. #define    MAXPACKET    PACKETSZ
  46. #else
  47. #define    MAXPACKET    1024
  48. #endif
  49.  
  50. typedef union {
  51.     HEADER hdr;
  52.     u_char buf[MAXPACKET];
  53. } querybuf;
  54.  
  55. static union {
  56.     long al;
  57.     char ac;
  58. } align;
  59.  
  60.  
  61. int h_errno;
  62. extern errno;
  63.  
  64. static struct hostent *
  65. getanswer(answer, anslen, iquery)
  66.     querybuf *answer;
  67.     int anslen;
  68.     int iquery;
  69. {
  70.     register HEADER *hp;
  71.     register u_char *cp;
  72.     register int n;
  73.     u_char *eom;
  74.     char *bp, **ap;
  75.     int type, class, buflen, ancount, qdcount;
  76.     int haveanswer, getclass = C_ANY;
  77.     char **hap;
  78.  
  79.     eom = answer->buf + anslen;
  80.     /*
  81.      * find first satisfactory answer
  82.      */
  83.     hp = &answer->hdr;
  84.     ancount = ntohs(hp->ancount);
  85.     qdcount = ntohs(hp->qdcount);
  86.     bp = hostbuf;
  87.     buflen = sizeof(hostbuf);
  88.     cp = answer->buf + sizeof(HEADER);
  89.     if (qdcount) {
  90.         if (iquery) {
  91.             if ((n = dn_expand(answer->buf, eom,
  92.                  cp, (u_char *) bp, buflen)) < 0) {
  93.                 h_errno = NO_RECOVERY;
  94.                 return ((struct hostent *) NULL);
  95.             }
  96.             cp += n + QFIXEDSZ;
  97.             host.h_name = bp;
  98.             n = strlen(bp) + 1;
  99.             bp += n;
  100.             buflen -= n;
  101.         } else
  102.             cp += dn_skipname(cp, eom) + QFIXEDSZ;
  103.         while (--qdcount > 0)
  104.             cp += dn_skipname(cp, eom) + QFIXEDSZ;
  105.     } else if (iquery) {
  106.         if (hp->aa)
  107.             h_errno = HOST_NOT_FOUND;
  108.         else
  109.             h_errno = TRY_AGAIN;
  110.         return ((struct hostent *) NULL);
  111.     }
  112.     ap = host_aliases;
  113.     host.h_aliases = host_aliases;
  114.     hap = h_addr_ptrs;
  115. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  116.     host.h_addr_list = h_addr_ptrs;
  117. #endif
  118.     haveanswer = 0;
  119.     while (--ancount >= 0 && cp < eom) {
  120.         if ((n = dn_expand(answer->buf, eom, cp,
  121.             (u_char *) bp, buflen)) < 0)
  122.             break;
  123.         cp += n;
  124.         type = _getshort(cp);
  125.          cp += sizeof(u_short);
  126.         class = _getshort(cp);
  127.         cp += sizeof(u_short) + sizeof(u_long);
  128.         n = _getshort(cp);
  129.         cp += sizeof(u_short);
  130.         if (type == T_CNAME) {
  131.             cp += n;
  132.             if (ap >= &host_aliases[MAXALIASES-1])
  133.                 continue;
  134.             *ap++ = bp;
  135.             n = strlen(bp) + 1;
  136.             bp += n;
  137.             buflen -= n;
  138.             continue;
  139.         }
  140.         if (iquery && type == T_PTR) {
  141.             if ((n = dn_expand(answer->buf, eom,
  142.                 cp, (u_char *) bp, buflen)) < 0) {
  143.                 cp += n;
  144.                 continue;
  145.             }
  146.             cp += n;
  147.             host.h_name = bp;
  148.             return(&host);
  149.         }
  150.         if (iquery || type != T_A)  {
  151. #ifdef DEBUG
  152.             if (_res.options & RES_DEBUG)
  153.                 printf("unexpected answer type %d, size %d\n",
  154.                     type, n);
  155. #endif
  156.             cp += n;
  157.             continue;
  158.         }
  159.         if (haveanswer) {
  160.             if (n != host.h_length) {
  161.                 cp += n;
  162.                 continue;
  163.             }
  164.             if (class != getclass) {
  165.                 cp += n;
  166.                 continue;
  167.             }
  168.         } else {
  169.             host.h_length = n;
  170.             getclass = class;
  171.             host.h_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
  172.             if (!iquery) {
  173.                 host.h_name = bp;
  174.                 bp += strlen(bp) + 1;
  175.             }
  176.         }
  177.  
  178.         bp += sizeof(align) - ((u_long)bp % sizeof(align));
  179.  
  180.         if (bp + n >= &hostbuf[sizeof(hostbuf)]) {
  181. #ifdef DEBUG
  182.             if (_res.options & RES_DEBUG)
  183.                 printf("size (%d) too big\n", n);
  184. #endif
  185.             break;
  186.         }
  187.         bcopy((char *) cp, *hap++ = bp, n);
  188.         bp +=n;
  189.         cp += n;
  190.         haveanswer++;
  191.     }
  192.     if (haveanswer) {
  193.         *ap = NULL;
  194. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  195.         *hap = NULL;
  196. #else
  197.         host.h_addr = h_addr_ptrs[0];
  198. #endif
  199.         return (&host);
  200.     } else {
  201.         h_errno = TRY_AGAIN;
  202.         return ((struct hostent *) NULL);
  203.     }
  204. }
  205.  
  206. struct hostent *
  207. gethostbyname(name)
  208.     char *name;
  209. {
  210.     querybuf buf;
  211.     register char *cp;
  212.     int n;
  213.     extern struct hostent *_gethtbyname();
  214.  
  215.     /*
  216.      * disallow names consisting only of digits/dots, unless
  217.      * they end in a dot.
  218.      */
  219.     if (isdigit(name[0]))
  220.         for (cp = name;; ++cp) {
  221.             if (!*cp) {
  222.                 if (*--cp == '.')
  223.                     break;
  224.                 h_errno = HOST_NOT_FOUND;
  225.                 return ((struct hostent *) NULL);
  226.             }
  227.             if (!isdigit(*cp) && *cp != '.') 
  228.                 break;
  229.         }
  230.  
  231.     if ((n = res_search(name, C_IN, T_A, buf.buf, sizeof(buf))) < 0) {
  232. #ifdef DEBUG
  233.         if (_res.options & RES_DEBUG)
  234.             printf("res_search failed\n");
  235. #endif
  236.         return (_gethtbyname(name));
  237.     }
  238.     return (getanswer(&buf, n, 0));
  239. }
  240.  
  241. struct hostent *
  242. gethostbyaddr(addr, len, type)
  243.     char *addr;
  244.     int len, type;
  245. {
  246.     int n;
  247.     querybuf buf;
  248.     register struct hostent *hp;
  249.     char qbuf[MAXDNAME];
  250.     extern struct hostent *_gethtbyaddr();
  251.  
  252.     if (type != AF_INET)
  253.         return ((struct hostent *) NULL);
  254.     (void)sprintf(qbuf, "%d.%d.%d.%d.in-addr.arpa",
  255.         ((unsigned)addr[3] & 0xff),
  256.         ((unsigned)addr[2] & 0xff),
  257.         ((unsigned)addr[1] & 0xff),
  258.         ((unsigned)addr[0] & 0xff));
  259.     n = res_query(qbuf, C_IN, T_PTR, (u_char *)&buf, sizeof(buf));
  260.     if (n < 0) {
  261. #ifdef DEBUG
  262.         if (_res.options & RES_DEBUG)
  263.             printf("res_query failed\n");
  264. #endif
  265.         if (errno == ECONNREFUSED)
  266.             return (_gethtbyaddr(addr, len, type));
  267.         return ((struct hostent *) NULL);
  268.     }
  269.     hp = getanswer(&buf, n, 1);
  270.     if (hp == NULL)
  271.         return ((struct hostent *) NULL);
  272.     hp->h_addrtype = type;
  273.     hp->h_length = len;
  274.     h_addr_ptrs[0] = (char *)&host_addr;
  275.     h_addr_ptrs[1] = (char *)0;
  276.     host_addr = *(struct in_addr *)addr;
  277.     return(hp);
  278. }
  279.  
  280. _sethtent(f)
  281.     int f;
  282. {
  283.     if (hostf == NULL)
  284.         hostf = fopen(HOSTDB, "r" );
  285.     else
  286.         rewind(hostf);
  287.     stayopen |= f;
  288. }
  289.  
  290. _endhtent()
  291. {
  292.     if (hostf && !stayopen) {
  293.         (void) fclose(hostf);
  294.         hostf = NULL;
  295.     }
  296. }
  297.  
  298. struct hostent *
  299. _gethtent()
  300. {
  301.     char *p;
  302.     register char *cp, **q;
  303.  
  304.     if (hostf == NULL && (hostf = fopen(HOSTDB, "r" )) == NULL)
  305.         return (NULL);
  306. again:
  307.     if ((p = fgets(hostbuf, BUFSIZ, hostf)) == NULL)
  308.         return (NULL);
  309.     if (*p == '#')
  310.         goto again;
  311.     cp = any(p, "#\n");
  312.     if (cp == NULL)
  313.         goto again;
  314.     *cp = '\0';
  315.     cp = any(p, " \t");
  316.     if (cp == NULL)
  317.         goto again;
  318.     *cp++ = '\0';
  319.     /* THIS STUFF IS INTERNET SPECIFIC */
  320. #if BSD >= 43 || defined(h_addr)    /* new-style hostent structure */
  321.     host.h_addr_list = host_addrs;
  322. #endif
  323.     host.h_addr = hostaddr;
  324.     *((u_long *)host.h_addr) = inet_addr(p);
  325.     host.h_length = sizeof (u_long);
  326.     host.h_addrtype = AF_INET;
  327.     while (*cp == ' ' || *cp == '\t')
  328.         cp++;
  329.     host.h_name = cp;
  330.     q = host.h_aliases = host_aliases;
  331.     cp = any(cp, " \t");
  332.     if (cp != NULL) 
  333.         *cp++ = '\0';
  334.     while (cp && *cp) {
  335.         if (*cp == ' ' || *cp == '\t') {
  336.             cp++;
  337.             continue;
  338.         }
  339.         if (q < &host_aliases[MAXALIASES - 1])
  340.             *q++ = cp;
  341.         cp = any(cp, " \t");
  342.         if (cp != NULL)
  343.             *cp++ = '\0';
  344.     }
  345.     *q = NULL;
  346.     return (&host);
  347. }
  348.  
  349. static char *
  350. any(cp, match)
  351.     register char *cp;
  352.     char *match;
  353. {
  354.     register char *mp, c;
  355.  
  356.     while (c = *cp) {
  357.         for (mp = match; *mp; mp++)
  358.             if (*mp == c)
  359.                 return (cp);
  360.         cp++;
  361.     }
  362.     return ((char *)0);
  363. }
  364.  
  365. struct hostent *
  366. _gethtbyname(name)
  367.     char *name;
  368. {
  369.     register struct hostent *p;
  370.     register char **cp;
  371.     
  372.     _sethtent(0);
  373.     while (p = _gethtent()) {
  374.         if (strcasecmp(p->h_name, name) == 0)
  375.             break;
  376.         for (cp = p->h_aliases; *cp != 0; cp++)
  377.             if (strcasecmp(*cp, name) == 0)
  378.                 goto found;
  379.     }
  380. found:
  381.     _endhtent();
  382.     return (p);
  383. }
  384.  
  385. struct hostent *
  386. _gethtbyaddr(addr, len, type)
  387.     char *addr;
  388.     int len, type;
  389. {
  390.     register struct hostent *p;
  391.  
  392.     _sethtent(0);
  393.     while (p = _gethtent())
  394.         if (p->h_addrtype == type && !bcmp(p->h_addr, addr, len))
  395.             break;
  396.     _endhtent();
  397.     return (p);
  398. }
  399.